package org.xx.armory.log4j2;

import org.apache.logging.log4j.core.appender.AppenderLoggingException;
import org.apache.logging.log4j.nosql.appender.DefaultNoSqlObject;
import org.apache.logging.log4j.nosql.appender.NoSqlConnection;
import org.apache.logging.log4j.nosql.appender.NoSqlObject;
import org.xx.armory.commons.CalledBy;
import redis.clients.jedis.Jedis;

import java.util.Map;

import static org.apache.commons.lang3.StringUtils.isBlank;
import static org.xx.armory.commons.JsonUtils.toJson;

/**
 * 访问Redis数据库的连接。
 */
public class RedisConnection
        implements NoSqlConnection<Map<String, Object>, DefaultNoSqlObject> {
    private final Jedis jedis;
    private final String key;

    /**
     * 构造访问Redis数据库的连接对象。
     *
     * @param jedis
     *         Redis对象。
     * @param key
     *         保存日志的键名。
     */
    @CalledBy("log4j2")
    public RedisConnection(
            Jedis jedis,
            String key
    ) {
        if (jedis == null) {
            throw new AppenderLoggingException("argument \"jedis\" cannot be null");
        }
        if (isBlank(key)) {
            throw new AppenderLoggingException("argument \"key\" cannot be blank");
        }

        this.jedis = jedis;
        this.key = key.trim();
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public DefaultNoSqlObject createObject() {
        return new DefaultNoSqlObject();
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public DefaultNoSqlObject[] createList(
            int length
    ) {
        return new DefaultNoSqlObject[length];
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void insertObject(NoSqlObject<Map<String, Object>> object) {
        try {
            // 将需要输出的对象追加到列表的尾部。
            jedis.rpush(key, toJson(object.unwrap()));
        } catch (Exception ex) {
            throw new AppenderLoggingException("cannot push data to redis", ex);
        }
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void close() {
        this.jedis.close();
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public boolean isClosed() {
        return !this.jedis.isConnected();
    }

}
